package fons.navigator.views.island;

import java.awt.Color;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import edu.umd.cs.piccolo.PCamera;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.util.PBounds;
import fons.navigator.util.piccolo.PNodes;

public class MapGrid extends PNode {
	private static final long serialVersionUID = 1L;

	public class MapQuad extends PPath {
		private static final long serialVersionUID = 1L;
		private final int x, y;
		
		public MapQuad (int x, int y, double width, double height) {
			super(new Rectangle2D.Double(0, 0, width + 4, height + 4));
			this.x = x;
			this.y = y;
			this.setOffset(x*width - 2, y*height - 2);
			this.setPaint(new Color((float) Math.random(), (float) Math.random(), (float) Math.random()));
			this.setStroke(null);
		}

		public void update(double x, double y, double width, double height) {
			final double posX = x + this.x*width, posY = y + this.y*height;
			this.setOffset(posX - 2, posY - 2);
			this.setWidth(width + 4);
			this.setHeight(height + 4);
			updateColor();
		}
		
		public void updateColor() {
			final double posX = this.getXOffset() + 2;
			final double posY = this.getYOffset() + 2;
			this.setPaint(getColorField().at(posX*visualIsland.getValueScale(), posY*visualIsland.getValueScale(), this));
		}
		
	}
	
	private final VisualIsland visualIsland;

	public MapGrid(VisualIsland visualIsland) {
		this.visualIsland = visualIsland;
		
		final double width = visualIsland.getCamera().getViewBounds().width / visualIsland.getResolutionX();
		final double height = visualIsland.getCamera().getViewBounds().height / visualIsland.getResolutionY();
		
		for (int x = 0; x < visualIsland.getResolutionX(); ++x) {
			for (int y = 0; y < visualIsland.getResolutionY(); ++y) {
				this.addChild(new MapQuad(x, y, width, height));
			}
		}
		
		visualIsland.getCamera().addPropertyChangeListener(new PropertyChangeListener () {
			public void propertyChange(PropertyChangeEvent evt) {
				if (evt.getPropertyName() == PCamera.PROPERTY_BOUNDS
				 || evt.getPropertyName() == PCamera.PROPERTY_VIEW_TRANSFORM) {
					update();
				}
			}
		});
	}
	
	public void update() {
		final PCamera cam = visualIsland.getCamera();
		final PBounds bounds = cam.getViewBounds();
		
		for (MapQuad quad: PNodes.childrenOfType(this, MapQuad.class)) {
			quad.update(bounds.x, bounds.y,
					bounds.width / (double) visualIsland.getResolutionX(), 
					bounds.height / (double) visualIsland.getResolutionY());
		}
	}
	
	public void updateColors() {
		for (MapQuad quad: PNodes.childrenOfType(this, MapQuad.class)) {
			quad.updateColor();
		}
	}
	
	public ColorField getColorField() {
		return visualIsland.getMapModel().getColorField();
	}
	
	public double getQuadWidth() {
		final PBounds bounds = visualIsland.getCamera().getViewBounds();
		return bounds.width / (double) visualIsland.getResolutionX();
	}
	
	public double getQuadHeight() {
		final PBounds bounds = visualIsland.getCamera().getViewBounds();
		return bounds.height / (double) visualIsland.getResolutionY();
	}
}
